home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / gnu_oleo_1_2_2.lha / oleo-1.2.2 / io-x11.c < prev    next >
C/C++ Source or Header  |  1993-03-03  |  59KB  |  2,599 lines

  1. #ifdef HAVE_X11_X_H
  2. /*    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this software; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18.  
  19. #include  <stdio.h>
  20. #include <ctype.h>
  21. #include <sys/param.h>
  22. #define NeedFunctionPrototypes 0
  23. #include <X11/X.h>
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #include <X11/Xresource.h>
  27. #include <X11/keysym.h>
  28. #include "global.h"
  29. #include "io-generic.h"
  30. #include "io-edit.h"
  31. #include "io-utils.h"
  32. #include "io-term.h"
  33. #include "window.h"
  34. #include "line.h"
  35. #include "font.h"
  36. #include "lists.h"
  37. #include "display.h"
  38. #include "io-abstract.h"
  39. #include "regions.h"
  40. #include "math.h"
  41.  
  42.  
  43. #if defined(HAVE_RINT)
  44. #ifdef __STDC__
  45. extern double rint (double);
  46. #else
  47. extern double rint ();
  48. #endif
  49. #else
  50. #define rint(x) (((x)<0) ? ceil((x)-.5) : floor((x)+.5))
  51. #endif
  52. static void record_damage ();
  53.  
  54. #ifdef __STDC__
  55. extern char * x_get_string_resource (XrmDatabase, char *, char *);
  56. extern XrmDatabase x_load_resources (Display *, char *, char *);
  57. extern char * getenv (const char *);
  58. #else
  59. extern char * x_get_string_resource ();
  60. extern XrmDatabase x_load_resources ();
  61. extern char * getenv ();
  62. #endif
  63.  
  64.  
  65. static char *emergency_font_name = "8x13";
  66. static char *cell_font_name = "times_roman12";
  67. static char *default_font_name = "8x13";
  68. static char *input_font_name = "8x13";
  69. static char *status_font_name = "6x10";
  70. static char *text_line_font_name = "8x13";
  71. static char *label_font_name = "5x8";
  72. static int cell_font_point_size = 12;
  73. static char *default_bg_color_name = "black";
  74. static char *default_fg_color_name = "white";
  75.  
  76. /* If non-0 and !no_x, these display functions will be used. */
  77. char *io_x11_display_name = 0;
  78.  
  79. /* The geometry of the first window. */
  80. static int geom_x = 0;
  81. static int geom_y = 0;
  82. static int geom_w = 675;
  83. static int geom_h = 350;
  84. static char geom_string[] = "675x350+0+0";
  85.  
  86. /* This global is used only during command line and .Xdefaults handling. */
  87. static Display * theDisplay;
  88.  
  89. static char * rdb_class_name = "Oleo";
  90. static char * rdb_name = "oleo";
  91.  
  92. #if 0
  93. static XrmOptionDescRec x11_options[] =
  94. {
  95.   {0, 0, 0, 0}
  96. };
  97.  
  98. /* This dynamicly computes the size of x11_options to make 
  99.  * upkeep of this file less error prone.
  100.  */
  101. static int
  102. count_options ()
  103. {
  104.   int x;
  105.   for (x = 0; x11_options[x].option; ++x)
  106.     ;
  107.   return x;
  108. }
  109. #endif
  110. /* This synthesizes class and generic names for resources (fancy strcat).
  111.  * Memory is reused after a reasonable number of calls. 
  112.  */
  113. #define RDB_NAME_BUF    8
  114. #define RDB_NAME_SIZE    256
  115.  
  116. static char * 
  117. resource_name (left, right)
  118.      char * left;
  119.      char * right;
  120. {
  121.   static char bufs[RDB_NAME_BUF][RDB_NAME_SIZE];
  122.   static int buf_pos = 0;
  123.   int len = strlen(left);
  124.  
  125.   bcopy (left, bufs[buf_pos], len);
  126.   bufs[buf_pos][len] = '.';
  127.   strcpy (bufs[buf_pos] + len + 1, right);
  128.   return bufs [buf_pos++];
  129. }
  130.  
  131. static char *
  132. class_of (foo)
  133.      char * foo;
  134. {
  135.   return resource_name (rdb_class_name, foo);
  136. }
  137.  
  138. static char *
  139. name_of (foo)
  140.      char * foo;
  141. {
  142.   return resource_name (rdb_name, foo);
  143. }
  144.  
  145. static XrmDatabase rdb;
  146.  
  147. #ifdef __STDC__
  148. void
  149. get_x11_args (int * argc_p, char ** argv)
  150. #else
  151. void
  152. get_x11_args (argc_p, argv)
  153.      int * argc_p;
  154.      char ** argv;
  155. #endif
  156. {
  157.   XrmInitialize ();
  158.  
  159. #if 0
  160.   XrmDatabase argv_resources;
  161.   /* Get the command line arguments. */
  162.   XrmParseCommand (&argv_resources, x11_options,
  163.            count_options (x11_options),
  164.            rdb_name, argc_p, argv);
  165.  
  166.   /* Compute the display from either resources or getenv. */
  167.   
  168.   io_x11_display_name =
  169.     x_get_string_resource (argv_resources, class_of ("Display"),
  170.                name_of ("display"));
  171. #endif                           
  172.   if (!io_x11_display_name)
  173.     io_x11_display_name = ck_savestr (getenv ("DISPLAY"));
  174.  
  175.   if (!io_x11_display_name)
  176.     return;
  177.  
  178.   theDisplay = XOpenDisplay (io_x11_display_name);
  179.   if (!theDisplay)
  180.     panic ("Can not connect to X.  Check your DISPLAY evironment variable.");
  181.  
  182.   FD_SET (ConnectionNumber (theDisplay), &read_fd_set);
  183.   FD_SET (ConnectionNumber (theDisplay), &exception_fd_set);
  184.  
  185.   /* Load the resource databases in a manner not unlike emacs :). */
  186.   rdb = x_load_resources (theDisplay, 0, rdb_class_name);
  187.  
  188. #if 0
  189.   /* Merge in the command line database.  */
  190.   XrmMergeDatabases (argv_resources, rdb);
  191. #endif
  192.  
  193.   /* Set up the various defaults (staticly declared above). */
  194.   {
  195.     char * val;
  196.  
  197.     val = x_get_string_resource (rdb, class_of ("Foreground"),
  198.                  name_of("foreground"));
  199.     if (val)
  200.       default_fg_color_name = val;
  201.  
  202.     val = x_get_string_resource (rdb, class_of ("Background"),
  203.                  name_of("background"));
  204.     if (val)
  205.       default_bg_color_name = val;
  206.  
  207.     val = x_get_string_resource (rdb, class_of ("Geometry"),
  208.                  name_of("geometry"));
  209.     if (val)
  210.       XGeometry (theDisplay, DefaultScreen(theDisplay), val, geom_string,
  211.          0, 1, 1, 0, 0, &geom_x, &geom_y, &geom_w, &geom_h);
  212.   }
  213. }
  214.  
  215.  
  216. static int x11_opened = 0;
  217. static struct sXport *thePort;
  218. typedef struct sXport *Xport;
  219.  
  220. struct sXport
  221. {
  222.   Display *dpy;
  223.   int screen;
  224.   Colormap color_map;
  225.   XColor fg_color;
  226.   XColor bg_color;
  227.   unsigned long fg_color_pixel;
  228.   unsigned long bg_color_pixel;
  229.   Window window;
  230.   Cursor mouse_cursor;
  231.  
  232.   XFontStruct *input_font;
  233.   XFontStruct *text_line_font;
  234.   XFontStruct *label_font;
  235.   XFontStruct *status_font;
  236.  
  237.   GC neutral_gc;
  238.   GC normal_gc;
  239.   GC standout_gc;
  240.   GC input_gc;
  241.   GC standout_input_gc;
  242.   GC text_line_gc;
  243.   GC text_line_standout_gc;
  244.   GC label_gc;
  245.   GC label_standout_gc;
  246.   GC status_gc;
  247.  
  248.   struct x_window *xwins;
  249.   int cursor_visible;        /* init to 1 */
  250.   int redisp_needed;
  251. };
  252.  
  253. static void
  254. beep (xport)
  255.      Xport xport;
  256. {
  257.   XBell (xport->dpy, 30);
  258.   XFlush (xport->dpy);
  259. }
  260.  
  261.  
  262. /****************************************************************
  263.  * Low level Input
  264.  ****************************************************************/
  265.  
  266. /* To be like curses, we offer this option: */
  267. static int block_on_getch = 1;
  268.  
  269. /* This is the buffer of decoded keyboard events. */
  270. static char *input_buf = 0;
  271. static int input_buf_allocated = 0;
  272. static int chars_buffered = 0;
  273. #define MAX_KEY_TRANSLATION    (1024)
  274.  
  275. static void
  276. xio_scan_for_input (blockp)
  277.      int blockp;
  278. {
  279.   XEvent event_return;
  280.   static int pendingw;
  281.   static int pendingh;
  282.   static int resize_pending = 0;
  283.   int events_pending;
  284.   int len;
  285.  
  286.   events_pending = XPending (thePort->dpy);
  287.   do
  288.     {
  289.       if (resize_pending && !events_pending)
  290.     {
  291.       io_set_scr_size (pendingh, pendingw);
  292.       resize_pending = 0;
  293.     }
  294.  
  295.       if (!events_pending)
  296.     io_redisp ();
  297.  
  298.       if (events_pending || blockp)
  299.     XNextEvent (thePort->dpy, &event_return);
  300.       else
  301.     return;
  302.  
  303.       switch (event_return.type)
  304.     {
  305.     case KeyPress:
  306.     case ButtonPress:
  307.     case ButtonRelease:
  308.       if (chars_buffered + MAX_KEY_TRANSLATION >= input_buf_allocated)
  309.         {
  310.           input_buf_allocated =
  311.         2 * (input_buf_allocated
  312.              ? input_buf_allocated
  313.              : MAX_KEY_TRANSLATION);
  314.           input_buf =
  315.         (char *) ck_remalloc (input_buf, input_buf_allocated);
  316.         }
  317.     }
  318.  
  319.  
  320.       switch (event_return.type)
  321.     {
  322.     case KeyPress:
  323.       len = XLookupString (&event_return,
  324.                input_buf + chars_buffered,
  325.                MAX_KEY_TRANSLATION, 0, 0);
  326.       if ((len == 1) && (event_return.xkey.state & Mod1Mask))
  327.         input_buf[chars_buffered] |= 0x80;
  328.       chars_buffered += len;
  329.       break;
  330.  
  331.     case ButtonPress:
  332.     case ButtonRelease:
  333.       {
  334.         int seq =
  335.         enqueue_mouse_event (event_return.xbutton.y,
  336.                  event_return.xbutton.x,
  337.                  event_return.xbutton.button,
  338.                  event_return.type == ButtonPress);
  339.         input_buf[chars_buffered++] = MOUSE_CHAR;
  340.         input_buf[chars_buffered++] =
  341.           event_return.xbutton.button - 1 + '0';
  342.         input_buf[chars_buffered++] = (char) seq;
  343.         break;
  344.       }
  345.  
  346.     case Expose:
  347.       record_damage (thePort,
  348.              event_return.xexpose.x, event_return.xexpose.y,
  349.              event_return.xexpose.width,
  350.              event_return.xexpose.height);
  351.       break;
  352.  
  353.     case MapNotify:
  354.       break;
  355.  
  356.     case ReparentNotify:
  357.       break;
  358.  
  359.     case ConfigureNotify:
  360.       pendingw = event_return.xconfigure.width;
  361.       pendingh = event_return.xconfigure.height;
  362.       resize_pending = 1;
  363.       break;
  364.  
  365.     default:
  366.       break;
  367.     }
  368.       events_pending = XPending (thePort->dpy);
  369.     }
  370.   while (events_pending || !chars_buffered);
  371. }
  372.  
  373. static int
  374. xio_input_avail ()
  375. {
  376.   return chars_buffered;
  377. }
  378.  
  379. static void
  380. xio_wait_for_input ()
  381. {
  382.   io_scan_for_input (1);
  383. }
  384.  
  385. static int
  386. xio_read_kbd (buffer, size)
  387.      VOLATILE char *buffer;
  388.      int size;
  389. {
  390.   int amt_read = size < chars_buffered ? size : chars_buffered;
  391.   bcopy (input_buf, (char *) buffer, amt_read);
  392.   chars_buffered -= amt_read;
  393.   if (chars_buffered)
  394.     bcopy ((char *) input_buf + amt_read, (char *) input_buf, chars_buffered);
  395.   return amt_read;
  396. }
  397.  
  398. static void
  399. xio_nodelay (delayp)
  400.      int delayp;
  401. {
  402.   block_on_getch = delayp;
  403. }
  404.  
  405. static int
  406. xio_getch ()
  407. {
  408.   char buf;
  409.  
  410.   if (!chars_buffered)
  411.     io_scan_for_input (block_on_getch);
  412.  
  413.   if (chars_buffered)
  414.     {
  415.       io_read_kbd (&buf, 1);
  416.       return buf;
  417.     }
  418.   else
  419.     return 0;
  420. }
  421.  
  422.  
  423. /****************************************************************
  424.  * Low level support for input and status areas.
  425.  ****************************************************************/
  426.  
  427. /*
  428.  * CRAM tells how many characters of a string will fit within
  429.  * a given number of cols, presuming that if they don't all fit,
  430.  * the string CONTINUE must be added to the end of those that do.
  431.  */
  432. static int
  433. cram (cols, font, text, len, continuation)
  434.      int cols;
  435.      XFontStruct *font;
  436.      char *text;
  437.      int len;
  438.      char *continuation;
  439. {
  440.   int cont_cols = XTextWidth (font, continuation, strlen (continuation));
  441.   int cols_used = 0;
  442.   int x = 0;
  443.  
  444.   if (XTextWidth (font, text, len) < cols)
  445.     return len;
  446.  
  447.   cols_used = 0;
  448.   while (x < len && cols_used < (cols - cont_cols))
  449.     cols_used += XTextWidth (font, text + x, 1);
  450.  
  451.   return x;
  452. }
  453.  
  454. static void
  455. draw_text_item (xport, c, r, wid, hgt, font, gc, text)
  456.      Xport xport;
  457.      int c;
  458.      int r;
  459.      int wid;
  460.      int hgt;
  461.      XFontStruct *font;
  462.      GC gc;
  463.      XTextItem *text;
  464. {
  465.   XRectangle clip;
  466.   int widused;
  467.   clip.x = c;
  468.   clip.y = r;
  469.   clip.width = wid;
  470.   clip.height = hgt;
  471.   if (!x11_opened)
  472.     return;
  473.   XSetClipRectangles (xport->dpy, gc, 0, 0, &clip, 1, YXBanded);
  474.   XDrawImageString (xport->dpy, xport->window, gc, c, r + font->ascent,
  475.             text->chars, text->nchars);
  476.   widused = XTextWidth (font, text->chars, text->nchars);
  477.   if (widused < wid)
  478.     XFillRectangle (xport->dpy, xport->window, xport->neutral_gc,
  479.             c + widused, r, wid - widused, hgt);
  480. }
  481.  
  482.  
  483. static void
  484. set_text (xtext, text, len)
  485.      XTextItem *xtext;
  486.      char *text;
  487.      int len;
  488. {
  489.   if (xtext->nchars < len)
  490.     {
  491.       xtext->chars = ck_remalloc (xtext->chars, len);
  492.       xtext->nchars = len;
  493.     }
  494.   bcopy (text, xtext->chars, len);
  495.   while (len < xtext->nchars)
  496.     xtext->chars[len++] = ' ';
  497. }
  498.  
  499.  
  500.  
  501. /*
  502.  * Low level interface to the input area specificly.
  503.  */
  504.  
  505. static XTextItem input_text;
  506. static int term_cursor_visible = 0;
  507. static int input_cursor = 0;    /* Position of cursor, if visible */
  508. static int textout;
  509. static int topclear = 0;
  510. static int input_more_mode = 0;
  511.  
  512. static void
  513. xio_cellize_cursor ()
  514. {
  515.   term_cursor_visible = 0;
  516. }
  517.  
  518. static void
  519. xio_inputize_cursor ()
  520. {
  521.   term_cursor_visible = 1;
  522. }
  523.  
  524. static void
  525. draw_input ()
  526. {
  527.   if (!input_text.chars)
  528.     {
  529.       XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  530.               input, 0, scr_cols, input_rows);
  531.       return;
  532.     }
  533.   input_text.font = thePort->input_font->fid;
  534.   draw_text_item (thePort, 0, input, scr_cols, input_rows, thePort->input_font,
  535.           thePort->input_gc, &input_text);
  536.   if (input_more_mode)
  537.     {
  538.       XTextItem more_text;
  539.       int mwid = XTextWidth (thePort->input_font, "[more]", 6);
  540.       more_text.chars = "[MORE]";
  541.       more_text.nchars = 6;
  542.       more_text.delta = 0;
  543.       more_text.font = thePort->input_font->fid;
  544.       draw_text_item (thePort, scr_cols - mwid, input, mwid, input_rows,
  545.            thePort->input_font, thePort->standout_input_gc, &more_text);
  546.     }
  547.   else if (term_cursor_visible)
  548.     {
  549.       int start = XTextWidth (thePort->input_font, input_text.chars, input_cursor);
  550.       int cwid = XTextWidth (thePort->input_font,
  551.                  input_text.chars + input_cursor, 1);
  552.       XTextItem cursor_text;
  553.       cursor_text.chars = input_text.chars + input_cursor;
  554.       cursor_text.nchars = 1;
  555.       cursor_text.font = thePort->input_font->fid;
  556.       draw_text_item (thePort, start, input, cwid, input_rows,
  557.               thePort->input_font, thePort->standout_input_gc,
  558.               &cursor_text);
  559.     }
  560. }
  561.  
  562.  
  563. static void
  564. xio_clear_input_before ()
  565. {
  566.   textout = 0;
  567.   if (topclear == 2)
  568.     {
  569.       int x;
  570.       for (x = 0; x < input_text.nchars; ++x)
  571.     input_text.chars[x] = ' ';
  572.       input_cursor = 0;
  573.       draw_input ();
  574.       topclear = 0;
  575.     }
  576. }
  577.  
  578. static void
  579. xio_clear_input_after ()
  580. {
  581.   if (topclear)
  582.     {
  583.       int x;
  584.       for (x = 0; x < input_text.nchars; ++x)
  585.     input_text.chars[x] = ' ';
  586.       input_cursor = 0;
  587.       draw_input ();
  588.       topclear = 0;
  589.     }
  590. }
  591.  
  592. static void
  593. set_input (text, len, cursor)
  594.      char *text;
  595.      int len;
  596.      int cursor;
  597. {
  598.   set_text (&input_text, text, len);
  599.   if (cursor + 1 > input_text.nchars)
  600.     {
  601.       input_text.chars = (char *) ck_remalloc (input_text.chars, cursor + 1);
  602.       while (input_text.nchars < cursor + 1)
  603.     input_text.chars[input_text.nchars++] = ' ';
  604.     }
  605.   input_cursor = cursor;
  606.   draw_input ();
  607. }
  608.  
  609.  
  610. /*
  611.  * Low level interface to the status area specificly.
  612.  */
  613. static XTextItem status_text;
  614.  
  615. static void
  616. draw_status ()
  617. {
  618.   if (!x11_opened)
  619.     return;
  620.   if (user_status)
  621.     draw_text_item (thePort, 0, status, scr_cols,
  622.             status_rows, thePort->status_font,
  623.             thePort->status_gc, &status_text);
  624. }
  625.  
  626. static void
  627. set_status (text)
  628.      char *text;
  629. {
  630.   set_text (&status_text, text, strlen (text));
  631.   status_text.font = thePort->status_font->fid;
  632.   draw_status ();
  633. }
  634.  
  635.  
  636. /****************************************************************
  637.  * High level interfaces for the input and status areas.
  638.  ****************************************************************/
  639. static void
  640. xio_update_status ()
  641. {
  642.   CELL *cp;
  643.   char *dec;
  644.   char *ptr;
  645.   int plen;
  646.   int dlen;
  647.   int mplen;
  648.   char buf[1024];
  649.   char *assembled;
  650.   char *pos = buf;
  651.  
  652.   if (!user_status)
  653.     return;
  654.  
  655.   if (mkrow != NON_ROW)
  656.     {
  657.       struct rng r;
  658.       *pos++ = '*';
  659.       set_rng (&r, curow, cucol, mkrow, mkcol);
  660.       ptr = range_name (&r);
  661.     }
  662.   else
  663.     ptr = cell_name (curow, cucol);
  664.   bcopy (ptr, pos, strlen (ptr));
  665.   pos += strlen (ptr);
  666.   if (how_many != 1)
  667.     {
  668.       sprintf (pos, " {%u}", how_many);
  669.       pos += strlen (pos);
  670.     }
  671.   *pos++ = ' ';
  672.   mplen = XTextWidth (thePort->status_font, buf, pos - buf);
  673.  
  674.   if ((cp = find_cell (curow, cucol)) && cp->cell_formula)
  675.     {
  676.       dec = decomp (curow, cucol, cp);
  677.       dlen = XTextWidth (thePort->status_font, dec, strlen (dec));
  678.     }
  679.   else
  680.     {
  681.       dec = 0;
  682.       dlen = 0;
  683.     }
  684.  
  685.   ptr = cell_value_string (curow, cucol);
  686.   plen = XTextWidth (thePort->status_font, ptr, strlen (ptr));
  687.  
  688.   assembled = (char *) ck_malloc (plen + dlen + mplen);
  689.   bcopy (buf, assembled, pos - buf);
  690.   pos = assembled + (pos - buf);
  691.  
  692.   {
  693.     int c;
  694.     int l;
  695.     int wid;
  696.  
  697.     l = strlen (ptr);
  698.     c = cram (scr_cols - mplen - thePort->status_font->max_bounds.width,
  699.           thePort->status_font, ptr, l, (dec ? " [...]" : "..."));
  700.     bcopy (ptr, pos, c);
  701.     pos += c;
  702.     if (c == l)
  703.       *pos++ = ' ';
  704.     else if (dec)
  705.       {
  706.     bcopy (" [...]", pos, 6);
  707.     pos += 6;
  708.     dec = 0;
  709.     dlen = 0;
  710.     decomp_free ();
  711.       }
  712.     else
  713.       {
  714.     bcopy ("...", pos, 3);
  715.     pos += 3;
  716.       }
  717.     *pos++ = ' ';
  718.     wid = XTextWidth (thePort->status_font, assembled, pos - assembled);
  719.  
  720.     if (dec)
  721.       {
  722.     l = strlen (dec);
  723.     c = cram (scr_cols - wid, thePort->status_font, dec, l, "[...]");
  724.     *pos++ = '[';
  725.     if (c < l)
  726.       {
  727.         bcopy (dec, pos, c);
  728.         bcopy ("...]", pos, 4);
  729.         pos += c + 4;
  730.       }
  731.     else
  732.       {
  733.         bcopy (dec, pos, c);
  734.         pos += c;
  735.         *pos++ = ']';
  736.       }
  737.       }
  738.  
  739.     *pos++ = '\0';
  740.     set_status (assembled);
  741.     draw_status ();
  742.     free (assembled);
  743.   }
  744. }
  745.  
  746. #ifdef __STDC__
  747. static void
  748. xio_info_msg (char *str,...)
  749. #else
  750. static void
  751. xio_info_msg (str, va_alist)
  752.      char *str;
  753.      va_dcl
  754. #endif
  755. {
  756.   va_list foo;
  757.   char buf[1000];
  758.  
  759.   var_start (foo, str);
  760.   vsprintf (buf, str, foo);
  761.   if (!user_status)
  762.     {
  763.       int len;
  764.       if (textout == 2)
  765.     {
  766.       input_more_mode = 1;
  767.       draw_input ();
  768.       (void) io_getch ();
  769.       input_more_mode = 0;
  770.     }
  771.       textout = 1;
  772.       len = strlen (buf);
  773.       set_input (buf, len, len);
  774.       draw_input ();
  775.     }
  776.   else
  777.     {
  778.       set_status (buf);
  779.       draw_status ();
  780.     }
  781. }
  782.  
  783. #ifdef __STDC__
  784. static void
  785. xio_error_msg (char *str,...)
  786. #else
  787. static void
  788. xio_error_msg (str, va_alist)
  789.      char *str;
  790.      va_dcl
  791. #endif
  792. {
  793.   va_list foo;
  794.   int len;
  795.   char buf[1000];
  796.  
  797.   var_start (foo, str);
  798.   vsprintf (buf, str, foo);
  799.  
  800.   if (textout == 2)
  801.     {
  802.       input_more_mode = 1;
  803.       draw_input ();
  804.       (void) io_getch ();
  805.       input_more_mode = 0;
  806.     }
  807.   else
  808.     textout = 2;
  809.  
  810.   len = strlen (buf);
  811.   set_input (buf, len, len);
  812.   topclear = 1;
  813. }
  814.  
  815.  
  816. static int
  817. xio_get_chr (prompt)
  818.      char *prompt;
  819. {
  820.   int len = strlen (prompt);
  821.   set_input (prompt, len, len);
  822.   topclear = 2;
  823.   draw_input ();
  824.   return io_getch ();
  825. }
  826.  
  827. #define BUFFER 10
  828.  
  829. #define MORE(bytes)                \
  830.   line_len+=bytes;                \
  831.   line->buf=ck_realloc(sptr,line_len+1);    \
  832.   eptr= eptr-sptr + line->buf;            \
  833.   ptr= ptr-sptr + line->buf;            \
  834.   sptr= line->buf;
  835.  
  836. #define KILLCH()                \
  837. {                        \
  838.  if(ptr!=eptr) {                \
  839.    char *tptr;                    \
  840.    for(tptr=ptr;tptr<=eptr;tptr++)         \
  841.      tptr[-1]= tptr[0];                \
  842.  }                        \
  843.  --ptr;                        \
  844.  --eptr;                    \
  845.  --sfilled;                    \
  846. }
  847.  
  848. extern int was_mouse_goto;
  849. static int
  850. xio_get_line (prompt, line)
  851.      char *prompt;
  852.      struct line *line;
  853. {
  854.   static int reenter = 0;
  855.   static int over;        /* Overwrite or insert */
  856.   char *ptr;            /* Current position in the line */
  857.   char *sptr;            /* Start of the line */
  858.   char *eptr;            /* End of the line */
  859.   int line_len;            /* length of the line */
  860.   int plen;            /* Length of the prompt */
  861.   int c;
  862.   int sfilled;
  863.   char *in_str;
  864.   int n;
  865.   int do_free;
  866.   char vbuf[50];
  867.   int offset = 0;        /* visibility offset */
  868.   int prompt_wid;
  869.  
  870.   if (reenter)
  871.     return 2;
  872.   ++reenter;
  873.   topclear = 2;
  874.  
  875.   if (macro_func_arg)
  876.     {
  877.       set_line (line, macro_func_arg);
  878.       macro_func_arg = 0;
  879.       --reenter;
  880.       return 0;
  881.     }
  882.  
  883.   prompt_wid = (XTextWidth (thePort->input_font, prompt, strlen (prompt))
  884.         + XTextWidth (thePort->input_font, ": ", 2));
  885.   if (!line->alloc)
  886.     {
  887.       line->alloc = LINE_MIN;
  888.       line->buf = ck_malloc (LINE_MIN);
  889.       line->buf[0] = '\0';
  890.     }
  891.   line_len = line->alloc - 1;    /* Leave room for the NULL */
  892.   sptr = line->buf;
  893.  
  894.   sfilled = strlen (sptr);
  895.   plen = strlen (prompt);
  896.   ptr = sptr + sfilled;
  897.   eptr = ptr;
  898.   over = 0;
  899.  
  900.   input_active = 1;
  901.   term_cursor_visible = 1;
  902.   for (;;)
  903.     {
  904.       {
  905.     if (textout == 2)
  906.       {
  907.         /* [MORE] the error msg, so the luser has
  908.            a chance to see it. . . */
  909.         input_more_mode = 1;
  910.         draw_input ();
  911.         (void) get_chr ();
  912.         input_more_mode = 0;
  913.       }
  914.     textout = 0;
  915.     if (how_many != 1)
  916.       {
  917.         how_many = 1;
  918.         io_update_status ();
  919.       }
  920.  
  921.     {
  922.       static char *buf = 0;
  923.       int wid = XTextWidth (thePort->input_font, sptr, ptr - sptr);
  924.       if (prompt_wid + wid <= scr_cols)
  925.         offset = 0;
  926.       else if (!offset || offset > ptr - sptr ||
  927.            (prompt_wid
  928.             + XTextWidth (thePort->input_font,
  929.                   sptr + offset, ptr - sptr - offset)
  930.             >= scr_cols))
  931.         for (offset = ptr - sptr,
  932.          wid = XTextWidth (thePort->input_font, sptr + offset, 1);
  933.          ((wid < scr_cols - prompt_wid)
  934.           && (ptr - sptr - offset < BUFFER));
  935.          --offset, wid += XTextWidth (thePort->input_font, sptr + offset, 1))
  936.           ;
  937.       buf = (char *) ck_remalloc (buf, strlen (prompt) + 2 + eptr - sptr);
  938.       bcopy (prompt, buf, plen);
  939.       bcopy (": ", buf + plen, 2);
  940.       bcopy (sptr + offset, buf + plen + 2, eptr - sptr - offset);
  941.       set_input (buf, plen + 2 + eptr - sptr - offset, plen + 2 + ptr -
  942.              sptr - offset);
  943.     }
  944.       }
  945.  
  946.       term_cursor_visible = input_active;
  947.       map_chr (input_active ? EDIT_MAP : NAVIGATE_MAP);
  948.     swtch:
  949.       if (cur_vector != EDIT_VECTOR)
  950.     {
  951.       was_mouse_goto = 0;
  952.       n = global_cmd (input_active ? EDIT_MAP : NAVIGATE_MAP);
  953.       if (was_mouse_goto && last_mouse_event.location == MOUSE_ON_INPUT)
  954.         {
  955.           int cpos;
  956.           int max = eptr - sptr;
  957.           if (!input_active)
  958.         nicely_goto_window ((cwin - wins) % nwin);
  959.           for (cpos = 1; cpos < max; ++cpos)
  960.         if (XTextWidth (thePort->input_font, sptr + offset, cpos)
  961.             >= last_mouse_event.col - prompt_wid)
  962.           break;
  963.           ptr = sptr + offset + cpos - 1;
  964.         }
  965.       if (n == -3)
  966.         {
  967.           *eptr++ = '\0';
  968.           term_cursor_visible = 0;
  969.           --reenter;
  970.           input_active = 0;
  971.           window_after_input = -1;
  972.           return 2;
  973.         }
  974.       else if (n == -2)
  975.         {
  976.           beep (thePort);
  977.           beep (thePort);
  978.         }
  979.       else if (n >= 0)
  980.         goto swtch;
  981.       continue;
  982.     }
  983.       switch (cur_cmd - edit_funcs)
  984.     {
  985.     case L_BEG_LINE:
  986.       ptr = sptr;
  987.       break;
  988.  
  989.     case L_BK_CHR:
  990.       for (n = 0; ptr != sptr && n < how_many; n++)
  991.         --ptr;
  992.       break;
  993.  
  994.     case L_BK_WORD:
  995.       for (n = 0; ptr != sptr && n < how_many; n++)
  996.         {
  997.           while (ptr != sptr && !isalnum (ptr[-1]))
  998.         --ptr;
  999.           while (ptr != sptr && isalnum (ptr[-1]))
  1000.         --ptr;
  1001.         }
  1002.       break;
  1003.  
  1004.     case L_FW_DEL_CHR:
  1005.       for (n = 0; ptr != eptr && n < how_many; n++)
  1006.         {
  1007.           ptr++;
  1008.           KILLCH ()
  1009.         }
  1010.       break;
  1011.  
  1012.     case L_FW_DEL_WORD:
  1013.       for (n = 0; ptr != eptr && n < how_many; n++)
  1014.         {
  1015.           while (ptr != eptr && !isalnum (ptr[0]))
  1016.         {
  1017.           ptr++;
  1018.           KILLCH ()
  1019.         }
  1020.           while (ptr != eptr && isalnum (ptr[0]))
  1021.         {
  1022.           ptr++;
  1023.           KILLCH ()
  1024.         }
  1025.         }
  1026.       break;
  1027.  
  1028.     case L_END_LINE:
  1029.       ptr = eptr;
  1030.       break;
  1031.  
  1032.     case L_FW_CHR:
  1033.       for (n = 0; ptr != eptr && n < how_many; n++)
  1034.         ptr++;
  1035.       break;
  1036.  
  1037.     case L_FW_WORD:
  1038.       for (n = 0; ptr != eptr && n < how_many; n++)
  1039.         {
  1040.           while (ptr != eptr && !isalnum (ptr[0]))
  1041.         ptr++;
  1042.           while (ptr != eptr && isalnum (ptr[0]))
  1043.         ptr++;
  1044.         }
  1045.       break;
  1046.  
  1047.     case L_FW_DEL_END:
  1048.       eptr = ptr;
  1049.       break;
  1050.  
  1051.     case L_TOGGLE_OVER:
  1052.       over = !over;
  1053.       break;
  1054.  
  1055.     case L_BK_DEL_WORD:
  1056.       for (n = 0; ptr != sptr && n < how_many; n++)
  1057.         {
  1058.           while (ptr != sptr && !isalnum (ptr[-1]))
  1059.         KILLCH ()
  1060.           while (ptr != sptr && isalnum (ptr[-1]))
  1061.           KILLCH ()
  1062.           }
  1063.  
  1064.           break;
  1065.  
  1066.     case L_BK_DEL_END:
  1067.           while (ptr != sptr)
  1068.         KILLCH ()
  1069.           break;
  1070.  
  1071.     case L_BK_DEL_CHR:
  1072.           for (n = 0; ptr != sptr && n < how_many; n++)
  1073.         KILLCH ()
  1074.           break;
  1075.  
  1076.  
  1077.     case L_FINISH:
  1078.           *eptr++ = '\0';
  1079.           textout = 1;
  1080.           term_cursor_visible = 0;
  1081.           --reenter;
  1082.           input_active = 0;
  1083.           return eptr - sptr == 1 ? 1 : 0;
  1084.  
  1085.     case L_INS_EXPR:
  1086.           {
  1087.         CELL *cp;
  1088.         if (!(cp = find_cell (curow, cucol)))
  1089.           break;
  1090.         in_str = decomp (curow, cucol, cp);
  1091.         do_free = 1;
  1092.           }
  1093.           goto insert_string;
  1094.  
  1095.     case L_INS_VAL:
  1096.           in_str = cell_value_string (curow, cucol);
  1097.           do_free = 0;
  1098.           goto insert_string;
  1099.  
  1100.     case L_INS_REL:
  1101.           if (a0)
  1102.         {
  1103.           if (mkrow != NON_ROW)
  1104.             {
  1105.               struct rng r;
  1106.               set_rng (&r, curow, cucol, mkrow, mkcol);
  1107.               in_str = range_name (&r);
  1108.             }
  1109.           else
  1110.             in_str = cell_name (curow, cucol);
  1111.         }
  1112.           else
  1113.         {
  1114.           if (mkrow != NON_ROW)
  1115.             {
  1116.               switch (((curow == setrow) << 3)
  1117.                   + ((mkrow == setrow) << 2)
  1118.                   + ((cucol == setcol) << 1)
  1119.                   + (mkcol == setcol))
  1120.             {
  1121.             case 0:
  1122.             case 1:
  1123.             case 2:
  1124.             case 4:
  1125.             case 5:
  1126.             case 6:
  1127.             case 8:
  1128.             case 9:
  1129.             case 10:
  1130.               sprintf (vbuf, "r[%+d:%+d]c[%+d:%+d]",
  1131.                    (curow < mkrow ? curow : mkrow) - setrow,
  1132.                    (curow < mkrow ? mkrow : curow) - setrow,
  1133.                    (cucol < mkcol ? cucol : mkcol) - setcol,
  1134.                    (cucol < mkcol ? mkcol : cucol) - setcol);
  1135.               break;
  1136.  
  1137.             case 3:
  1138.             case 7:
  1139.             case 11:
  1140.               sprintf (vbuf, "r[%+d:%+d]c",
  1141.                    (curow < mkrow ? curow : mkrow) - setrow,
  1142.                    (curow < mkrow ? mkrow : curow) - setrow);
  1143.               break;
  1144.  
  1145.             case 12:
  1146.             case 14:
  1147.             case 13:
  1148.               sprintf (vbuf, "rc[%+d:%+d]",
  1149.                    (cucol < mkcol ? cucol : mkcol) - setcol,
  1150.                    (cucol < mkcol ? mkcol : cucol) - setcol);
  1151.               break;
  1152.  
  1153.             case 15:
  1154.               strcpy (vbuf, "rc");
  1155.               break;
  1156.             }
  1157.             }
  1158.  
  1159.           else
  1160.             {
  1161.               switch (((curow == setrow) << 1) + (cucol == setcol))
  1162.             {
  1163.             case 0:
  1164.               sprintf (vbuf, "r[%+d]c[%+d]", curow - setrow, cucol - setcol);
  1165.               break;
  1166.             case 1:
  1167.               sprintf (vbuf, "r[%+d]c", curow - setrow);
  1168.               break;
  1169.             case 2:
  1170.               sprintf (vbuf, "rc[%+d]", cucol - setcol);
  1171.               break;
  1172.             case 3:
  1173.               strcpy (vbuf, "rc");
  1174.               break;
  1175. #ifdef TEST
  1176.             default:
  1177.               panic ("huh what");
  1178. #endif
  1179.             }
  1180.             }
  1181.           in_str = vbuf;
  1182.         }
  1183.           do_free = 0;
  1184.           goto insert_string;
  1185.  
  1186.     case L_INS_ABS:
  1187.           /* Insert current cell/range name as an absolute reference */
  1188.           if (a0)
  1189.         {
  1190.           if (mkrow != NON_ROW)
  1191.             sprintf (vbuf, "$%s$%u:$%s:$%u", col_to_str (cucol), curow, col_to_str (mkcol), mkrow);
  1192.           else
  1193.             sprintf (vbuf, "$%s$%u", col_to_str (cucol), curow);
  1194.           in_str = vbuf;
  1195.         }
  1196.           else
  1197.         {
  1198.           if (mkrow != NON_ROW)
  1199.             {
  1200.               struct rng r;
  1201.  
  1202.               set_rng (&r, curow, cucol, mkrow, mkcol);
  1203.               in_str = range_name (&r);
  1204.             }
  1205.           else
  1206.             in_str = cell_name (curow, cucol);
  1207.         }
  1208.           do_free = 0;
  1209.  
  1210.         insert_string:
  1211.           c = strlen (in_str);
  1212.           if ((sfilled + (over ? c + (ptr - eptr) : c)) >= line_len)
  1213.         {
  1214.           n = over ? c + (ptr - eptr) : c;
  1215.           if (n < LINE_MIN)
  1216.             n = LINE_MIN;
  1217.           MORE (n);
  1218.         }
  1219.           if (over)
  1220.         {
  1221.           if (ptr + c > eptr)
  1222.             {
  1223.               sfilled += (ptr + c) - eptr;
  1224.               eptr = ptr + c;
  1225.             }
  1226.         }
  1227.           else
  1228.         {
  1229.           if (ptr != eptr)
  1230.             {
  1231.               char *tptr;
  1232.  
  1233.               for (tptr = eptr; tptr >= ptr; --tptr)
  1234.             tptr[c] = tptr[0];
  1235.             }
  1236.           eptr += c;
  1237.           sfilled += c;
  1238.         }
  1239.           bcopy (in_str, ptr, c);
  1240.           ptr += c;
  1241.           if (do_free)
  1242.         decomp_free ();
  1243.           break;
  1244.  
  1245.     case L_INS_CHR:
  1246.           if ((sfilled + how_many + (over ? (ptr - eptr) : (0))) >= line_len)
  1247.         {
  1248.           n = over ? how_many + (ptr - eptr) : how_many;
  1249.           if (n < LINE_MIN)
  1250.             n = LINE_MIN;
  1251.           MORE (n);
  1252.         }
  1253.           if (over)
  1254.         {
  1255.           if (ptr + how_many > eptr)
  1256.             {
  1257.               sfilled += (ptr + how_many) - eptr;
  1258.               eptr = ptr + how_many;
  1259.             }
  1260.         }
  1261.           else
  1262.         {
  1263.           if (ptr != eptr)
  1264.             {
  1265.               char *tptr;
  1266.  
  1267.               for (tptr = eptr; tptr >= ptr; --tptr)
  1268.             tptr[how_many] = tptr[0];
  1269.             }
  1270.           eptr += how_many;
  1271.           sfilled += how_many;
  1272.         }
  1273.           for (n = 0; n < how_many; n++)
  1274.         *ptr++ = cur_chr;
  1275.           break;
  1276.         }
  1277.     }
  1278. }
  1279. #undef KILLCH
  1280. #undef BUFFER
  1281. #undef MORE
  1282.  
  1283.  
  1284.   /*
  1285.  * Multi-line informational messages to the user:
  1286.  */
  1287. struct text_line
  1288. {
  1289.   struct text_line *next;
  1290.   int nchars;
  1291.   int standout;
  1292.   char line[TAIL_ARRAY];
  1293. };
  1294. static int text_damaged = 0;
  1295. static struct text_line *text_lines = 0;
  1296. static int text_rows;
  1297. static int save_auto;
  1298. extern int auto_recalc;
  1299.  
  1300.  
  1301. static void 
  1302. xio_text_start ()
  1303. {
  1304.   if (text_lines)
  1305.     io_text_finish ();
  1306.   XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  1307.           0, 0, scr_cols, scr_lines);
  1308.   save_auto = auto_recalc;
  1309.   auto_recalc = 0;
  1310.   text_rows = 0;
  1311. }
  1312.  
  1313. #define press_msg    "Press a key to to proceed:  "
  1314.  
  1315. static void
  1316. cons_text_line (txt, nchars, standout)
  1317.      char *txt;
  1318.      int nchars;
  1319.      int standout;
  1320. {
  1321.   struct text_line *line =
  1322.     (struct text_line *) ck_malloc (sizeof (*line) + nchars);
  1323.   line->next = text_lines;
  1324.   line->nchars = nchars;
  1325.   line->standout = standout;
  1326.   bcopy (txt, line->line, nchars);
  1327.   text_lines = line;
  1328.   text_rows += thePort->text_line_font->ascent + thePort->text_line_font->descent;
  1329. }
  1330.  
  1331. static void
  1332. xio_text_finish ()
  1333. {
  1334.   if (text_lines != 0)
  1335.     {
  1336.       cons_text_line (press_msg, strlen (press_msg), 1);
  1337.       text_damaged = 1;
  1338.       (void) io_getch ();
  1339.       while (text_lines)
  1340.     {
  1341.       struct text_line *t = text_lines;
  1342.       text_lines = text_lines->next;
  1343.       free (t);
  1344.     }
  1345.     }
  1346.   auto_recalc = save_auto;
  1347.   text_damaged = 1;
  1348.   draw_input ();
  1349.   draw_status ();
  1350. }
  1351.  
  1352.  
  1353. #ifdef __STDC__
  1354. static void
  1355. xio_text_line (char *ptr,...)
  1356. #else
  1357. static void
  1358. xio_text_line (ptr, va_alist)
  1359.      char *ptr;
  1360.      va_dcl
  1361. #endif
  1362. {
  1363.   va_list ap;
  1364.   char sav;
  1365.   char *next_ptr;
  1366.   int wid;
  1367.   int bs_cols;
  1368.   char buf[1000];
  1369.   
  1370.   var_start (ap, ptr);
  1371.   vsprintf (buf, ptr, ap);
  1372.   va_end (ap);
  1373.   ptr = buf;
  1374.   
  1375.   for (;;)
  1376.     {
  1377.       if (text_rows > (scr_lines - 2 * (thePort->text_line_font->ascent
  1378.                     + thePort->text_line_font->descent)))
  1379.     {
  1380.       cons_text_line (press_msg, strlen (press_msg), 1);
  1381.       text_damaged = 1;
  1382.       (void) io_getch ();
  1383.       while (text_lines)
  1384.         {
  1385.           struct text_line *l = text_lines;
  1386.           text_lines = text_lines->next;
  1387.           free (l);
  1388.         }
  1389.       text_rows = 0;
  1390.       XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  1391.               0, 0, scr_lines, scr_cols);
  1392.     }
  1393.       if (XTextWidth (thePort->text_line_font, ptr, strlen (ptr)) <= scr_cols)
  1394.     {
  1395.       cons_text_line (ptr, strlen (ptr), 0);
  1396.       break;
  1397.     }
  1398.       
  1399.       bs_cols = XTextWidth (thePort->text_line_font, "\\", 1);
  1400.       for (next_ptr = ptr, wid = 0;
  1401.        wid < scr_cols - bs_cols;
  1402.        ++next_ptr)
  1403.     wid += XTextWidth (thePort->text_line_font, next_ptr, 1);
  1404.       
  1405.       --next_ptr;
  1406.       sav = *(next_ptr - 1);
  1407.       *(next_ptr - 1) = '\\';
  1408.       cons_text_line (ptr, next_ptr - ptr, 0);
  1409.       *(next_ptr - 1) = sav;
  1410.       text_damaged = 1;
  1411.       ptr = next_ptr;
  1412.     }
  1413. }
  1414.  
  1415. /****************************************************************
  1416.  * Low level support for the cell windows.
  1417.  ****************************************************************/
  1418.  
  1419. /* Every cell has an associated font name.  This is a cache mapping
  1420.  * font names and scales to graphics contexts.
  1421.  */
  1422.  
  1423. struct cell_gc
  1424. {
  1425.   struct cell_gc *next;
  1426.   struct cell_gc *prev;
  1427.   Xport port;
  1428.   GC gc;
  1429.   char *font_name;
  1430.   double scale;
  1431.   XFontStruct *font;
  1432.   int clipped_to;
  1433.   int cursor:1;
  1434. };
  1435.  
  1436. /* The cell_gc cache is only valid for a specific size default font.  If the
  1437.  * defualt font size changes, then the cache must be flushed.
  1438.  */
  1439. static int cell_gc_basis = 12;
  1440.  
  1441.  
  1442. /* Individual cache entries are also validated by the clipping set for their
  1443.  * gc.  To the rest of the system, it appears that there is one clipping region
  1444.  * for all cell_gc's.
  1445.  */
  1446. static int clipcnt = 0;
  1447. static int cliprectc = 0;
  1448. static int cliprect_alloc = 0;
  1449. static XRectangle *cliprectv = 0;
  1450.  
  1451. #define GC_CACHE_SIZE    10
  1452. static struct cell_gc *cell_gc_cache = 0;
  1453.  
  1454.  
  1455. /* This takes the full name of an X11 font, and returns its point size (in
  1456.  * tenths of a point.  If the string is not a valid font name, 0 is returned.
  1457.  */
  1458. static int 
  1459. name_to_ps (xfont)
  1460.      char *xfont;
  1461. {
  1462.   while (*xfont)
  1463.     if (*xfont == '-')
  1464.       {
  1465.     ++xfont;
  1466.     if (*xfont == '-')    /* look for -- */
  1467.       {
  1468.         ++xfont;
  1469.         break;
  1470.       }
  1471.       }
  1472.   else
  1473.     ++xfont;
  1474.   if (!*xfont)
  1475.     return 0;
  1476.   while (isdigit (*xfont++));
  1477.   --xfont;
  1478.   if (!*xfont++ == '-')
  1479.     return 0;
  1480.   return atoi (xfont);
  1481. }
  1482.  
  1483.  
  1484. #define ABS(A) ((A) < 0 ? -(A) : (A))
  1485. static struct cell_gc *
  1486. cell_gc (port, font_passed, cursor)
  1487.      Xport port;
  1488.      struct font_memo *font_passed;
  1489.      int cursor;
  1490. {
  1491.   struct font_memo *font =
  1492.     (font_passed ? font_passed : default_font());
  1493.   char *font_name = font->name;
  1494.   double scale = font->scale;
  1495.   struct cell_gc *c = cell_gc_cache;
  1496.   if (cell_gc_basis != cell_font_point_size)
  1497.     {
  1498.       do
  1499.     {
  1500.       if (c->font_name)
  1501.         {
  1502.           XFreeFont (c->port->dpy, c->font);
  1503.           free (c->font_name);
  1504.         }
  1505.       c->font_name = 0;
  1506.       c->port = 0;
  1507.       c->font = 0;
  1508.       c = c->next;
  1509.     }
  1510.       while (c != cell_gc_cache);
  1511.       cell_gc_basis = cell_font_point_size;
  1512.     }
  1513.   else
  1514.     {
  1515.       do
  1516.     {
  1517.       if ((c->scale == scale)
  1518.           && port == c->port
  1519.           && c->font_name && !strcmp (font_name, c->font_name))
  1520.         {
  1521.           if (cell_gc_cache == c)
  1522.         cell_gc_cache = cell_gc_cache->next;
  1523.           c->next->prev = c->prev;
  1524.           c->prev->next = c->next;
  1525.           c->next = cell_gc_cache;
  1526.           c->prev = cell_gc_cache->prev;
  1527.           c->prev->next = c;
  1528.           c->next->prev = c;
  1529.           cell_gc_cache = c;
  1530.           goto check_clipping;
  1531.         }
  1532.       c = c->next;
  1533.     }
  1534.       while (c != cell_gc_cache);
  1535.     }
  1536.   
  1537.   c = c->prev;
  1538.   cell_gc_cache = c;
  1539.   if (c->font_name)
  1540.     {
  1541.       XFreeFont (c->port->dpy, c->font);
  1542.       free (c->font_name);
  1543.     }
  1544.   c->port = port;
  1545.   c->scale = scale;
  1546.   {
  1547.     char **fontv;
  1548.     int fontc;
  1549.     fontv = XListFonts (port->dpy, font_name, 1024, &fontc);
  1550.     if (fontv)
  1551.       {
  1552.     int x, best;
  1553.     int ideal_size = rint (scale * (double) cell_font_point_size * 10.);
  1554.     int best_dist;
  1555.     best = 0;
  1556.     best_dist = ideal_size - name_to_ps (fontv[0]);
  1557.     for (x = 1; x < fontc; ++x)
  1558.       {
  1559.         int ps = name_to_ps (fontv[x]);
  1560.         int tdist = ideal_size - ps;
  1561.         if (ABS (tdist) < ABS (best_dist)
  1562.         || ((ABS (tdist) == ABS (best_dist)) && (tdist > best_dist)))
  1563.           {
  1564.         best_dist = tdist;
  1565.         best = x;
  1566.           }
  1567.       }
  1568.     c->font = XLoadQueryFont (port->dpy, fontv[best]);
  1569.     XFreeFontNames (fontv);
  1570.       }
  1571.     else
  1572.       c->font = 0;
  1573.   }
  1574.   if (c->font)
  1575.     c->font_name = (char *) ck_savestr (font_name);
  1576.   else
  1577.     {
  1578.       c->font = XLoadQueryFont (port->dpy, cell_font_name);
  1579.       if (c->font)
  1580.     c->font_name = ck_savestr (cell_font_name);
  1581.       else
  1582.     {
  1583.       c->font = XLoadQueryFont (port->dpy, emergency_font_name);
  1584.       if (c->font)
  1585.         c->font_name = ck_savestr (emergency_font_name);
  1586.       else
  1587.         panic ("Unable to load even the emergency font.");
  1588.     }
  1589.     }
  1590.   
  1591.   {
  1592.     XGCValues v;
  1593.     v.font = c->font->fid;
  1594.     XChangeGC (port->dpy, c->gc, GCFont, &v);
  1595.   }
  1596.   
  1597.  check_clipping:
  1598.   
  1599.   if (clipcnt != c->clipped_to)
  1600.     {
  1601.       XSetClipRectangles (port->dpy, c->gc, 0, 0, cliprectv, cliprectc, Unsorted);
  1602.       c->clipped_to = clipcnt;
  1603.     }
  1604.   
  1605.   {
  1606.     XGCValues v;
  1607.     v.foreground = cursor ? port->bg_color_pixel : port->fg_color_pixel;
  1608.     v.background = cursor ? port->fg_color_pixel : port->bg_color_pixel;
  1609.     XChangeGC (port->dpy, c->gc, GCForeground | GCBackground, &v);
  1610.     c->cursor = cursor;
  1611.   }
  1612.   return c;
  1613. }
  1614.  
  1615. static void
  1616. collect_clipping (rect)
  1617.      xx_IntRectangle rect;
  1618. {
  1619.   if (cliprectc == cliprect_alloc)
  1620.     {
  1621.       cliprect_alloc = cliprect_alloc ? cliprect_alloc * 2 : 16;
  1622.       cliprectv =
  1623.     ((XRectangle *)
  1624.      ck_remalloc (cliprectv,
  1625.               cliprect_alloc * sizeof (XRectangle)));
  1626.     }
  1627.   cliprectv[cliprectc].x = rect->x;
  1628.   cliprectv[cliprectc].y = rect->y;
  1629.   cliprectv[cliprectc].width = rect->w;
  1630.   cliprectv[cliprectc].height = rect->h;
  1631.   ++cliprectc;
  1632. }
  1633.  
  1634. static void 
  1635. clip_to_intrectangle (rect)
  1636.      xx_IntRectangle rect;
  1637. {
  1638.   cliprectc = 0;
  1639.   collect_clipping (rect);
  1640.   ++clipcnt;
  1641. }
  1642.  
  1643.  
  1644. /* This is the data for an oleo window, displayed under X. */
  1645.  
  1646. enum kinds_of_layout_needed
  1647. {
  1648.   damaged_display = 1,
  1649.   new_display = 2
  1650. };
  1651.  
  1652. struct x_window
  1653. {
  1654.   struct x_window *next;
  1655.   struct window *win;
  1656.   struct display display;
  1657.   int layout_needed;
  1658.   int label_damage;
  1659.   Xport port;
  1660. };
  1661.  
  1662.  
  1663.  
  1664. #ifdef __STDC__
  1665. static void 
  1666. place_text (xx_IntRectangle out, struct display *disp, struct cell_display *cd, XFontStruct *font, char *string)
  1667. #else
  1668. static void 
  1669. place_text (out, disp, cd, font, string)
  1670.      xx_IntRectangle out;
  1671.      struct display *disp;
  1672.      struct cell_display *cd;
  1673.      XFontStruct *font;
  1674.      char *string;
  1675. #endif
  1676. {
  1677.   int *widths = disp->widths;
  1678.   int *heights = disp->heights;
  1679.   int *colx = disp->colx;
  1680.   int *rowy = disp->rowy;
  1681.   struct rng *range = &disp->range;
  1682.   int hout = font->ascent + font->descent;
  1683.   int wout = XTextWidth (font, string, strlen (string));
  1684.   int ci = cd->c - range->lc;
  1685.   int ri = cd->r - range->lr;
  1686.   int yout = rowy[ri] + heights[ri] - (font->ascent + font->descent);
  1687.   int xout;
  1688.   switch (cd->justification)
  1689.     {
  1690.     case JST_LFT:
  1691.       xout = colx[ci];
  1692.       break;
  1693.     case JST_RGT:
  1694.       xout = colx[ci] + widths[ci] - 1 - wout;
  1695.       break;
  1696.     case JST_CNT:
  1697.       xout = colx[ci] + (widths[ci] - wout) / 2;
  1698.       break;
  1699.     }
  1700.   xx_IRinit (out, xout, yout, wout, hout);
  1701. }
  1702.  
  1703.  
  1704. #ifdef __STDC__
  1705. static void
  1706. x_metric (struct cell_display *cd, struct display *disp)
  1707. #else
  1708. static void
  1709. x_metric (cd, disp)
  1710.      struct cell_display *cd;
  1711.      struct display *disp;
  1712. #endif
  1713. {
  1714.   struct x_window *xw = (struct x_window *) disp->vdata;
  1715.   Xport port = xw->port;
  1716.   if (!cd->unclipped)
  1717.     xx_IRinit (&cd->goal, 0, 0, 0, 0);
  1718.   else
  1719.     {
  1720.       struct cell_gc *cgc = cell_gc (port, cd->font, 0);
  1721.       place_text (&cd->goal, disp, cd, cgc->font, cd->unclipped);
  1722.     }
  1723. }
  1724.  
  1725.  
  1726. #ifdef __STDC__
  1727. static struct x_window *
  1728. x_win (Xport port, struct window *win, int rebuild)
  1729. #else
  1730. static struct x_window *
  1731. x_win (port, win, rebuild)
  1732.      Xport port;
  1733.      struct window *win;
  1734.      int rebuild;
  1735. #endif
  1736. {
  1737.   struct x_window *xw;
  1738.   
  1739.   for (xw = port->xwins; xw && xw->win != win; xw = xw->next);
  1740.   
  1741.   if (xw && !rebuild)
  1742.     return xw;
  1743.   
  1744.   if (xw)
  1745.     {
  1746.       free_display (&xw->display);
  1747.     }
  1748.   else
  1749.     {
  1750.       xw = (struct x_window *) ck_malloc (sizeof (*xw));
  1751.       xw->next = port->xwins;
  1752.       port->xwins = xw;
  1753.       xw->port = port;
  1754.     }
  1755.   xw->win = win;
  1756.   build_display (&xw->display, &win->screen, x_metric, xw);
  1757.   xw->label_damage = 1;
  1758.   xw->layout_needed = new_display;
  1759.   port->redisp_needed = 1;
  1760.   return xw;
  1761. }
  1762.  
  1763. #ifdef __STDC__
  1764. static void
  1765. flush_x_windows (Xport port)
  1766. #else
  1767. static void
  1768. flush_x_windows (port)
  1769.      Xport port;
  1770. #endif
  1771. {
  1772.   while (port->xwins)
  1773.     {
  1774.       struct x_window * xw = port->xwins;
  1775.       free_display (&xw->display);
  1776.       port->xwins = xw->next;
  1777.       free (xw);
  1778.       port->redisp_needed = 1;
  1779.     }
  1780. }
  1781.  
  1782.  
  1783.  
  1784. #ifdef __STDC__
  1785. static void
  1786. record_damage (Xport port, int x, int y, int w, int h)
  1787. #else
  1788. static void
  1789. record_damage (port, x, y, w, h)
  1790.      Xport port;
  1791.      int x;
  1792.      int y;
  1793.      int w;
  1794.      int h;
  1795. #endif
  1796. {
  1797.   struct x_window *xwin = port->xwins;
  1798.   
  1799.   if (text_lines)
  1800.     {
  1801.       text_damaged = 1;
  1802.       return;
  1803.     }
  1804.   
  1805.   while (xwin)
  1806.     {
  1807.       struct window *win = xwin->win;
  1808.       record_display_damage (&xwin->display,
  1809.                  x - win->win_over,
  1810.                  y - win->win_down,
  1811.                  w, h);
  1812.       port->redisp_needed = 1;
  1813.       if (   (   (x + w >= win->win_over - win_label_cols(win, win->screen.hr))
  1814.           && (x <= win->win_over)
  1815.           && (y + h >= win->win_down - win_label_rows(win))
  1816.           && (y <= win->win_down + display_height(&xwin->display)))
  1817.       || (   (y + h >= win->win_down - win_label_rows(win))
  1818.           && (y <= win->win_down)
  1819.           && (x + w >= win->win_over - win_label_cols(win, win->screen.hr))
  1820.           && (x <= win->win_over + display_width(&xwin->display))))
  1821.     xwin->label_damage = 1;
  1822.       xwin = xwin->next;
  1823.     }
  1824. }
  1825.  
  1826.  
  1827. #if __STDC__
  1828. static void
  1829. xio_pr_cell_win (struct window *win, CELLREF r, CELLREF c, CELL *cp)
  1830. #else
  1831. static void
  1832. xio_pr_cell_win (win, r, c, cp)
  1833.        struct window *win;
  1834.        CELLREF r;
  1835.        CELLREF c;
  1836.        CELL *cp;
  1837. #endif
  1838. {
  1839.   struct x_window *xwin = x_win (thePort, win, 0);
  1840.   struct display *disp = &xwin->display;
  1841.   
  1842.   if (pr_display_cell (disp, r, c, cp))
  1843.     {
  1844.       thePort->redisp_needed = 1;
  1845.       if (!xwin->layout_needed)
  1846.     xwin->layout_needed = damaged_display;
  1847.     }
  1848. }
  1849.  
  1850.  
  1851. #ifdef __STDC__
  1852. static void
  1853. xio_repaint_win (struct window *win)
  1854. #else
  1855. static void
  1856. xio_repaint_win (win)
  1857.      struct window *win;
  1858. #endif
  1859. {
  1860.   x_win (thePort, win, 1);
  1861.   XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  1862.           win->win_over, win->win_down, win->numc, win->numr);
  1863.   record_damage (thePort, win->win_over, win->win_down, win->numc, win->numr);
  1864. }
  1865.  
  1866.  
  1867. #ifdef __STDC__
  1868. static void
  1869. xio_repaint (void)
  1870. #else
  1871. static void
  1872. xio_repaint ()
  1873. #endif
  1874. {
  1875.   struct window *win;
  1876.   flush_x_windows (thePort);
  1877.   for (win = wins; win < &wins[nwin]; win++)
  1878.     xio_repaint_win (win);
  1879. }
  1880.  
  1881. #ifdef __STDC__
  1882. static void
  1883. draw_cell (struct x_window *xwin, struct cell_display *cd_passed, int cursor)
  1884. #else
  1885. static void
  1886. draw_cell (xwin, cd_passed, cursor)
  1887.      struct x_window *xwin;
  1888.      struct cell_display *cd_passed;
  1889.      int cursor;
  1890. #endif
  1891. {
  1892.   struct cell_display *cd = cd_passed->used_by;
  1893.   Xport port = xwin->port;
  1894.   struct window *win = xwin->win;
  1895.   int ov = win->win_over;
  1896.   int dn = win->win_down;
  1897.   CELLREF r = cd->r;
  1898.   CELLREF c = cd->c;
  1899.   struct display *disp = &xwin->display;
  1900.   int *rowy = disp->rowy;
  1901.   int *colx = disp->colx;
  1902.   int *widths = disp->widths;
  1903.   int *heights = disp->heights;
  1904.   struct cell_gc *cgc;
  1905.   int ri = r - disp->range.lr;
  1906.   int ci = c - disp->range.lc;
  1907.   
  1908.   if (!(widths[ci] && heights[ri]))
  1909.     return;
  1910.   
  1911.   if (!cd->unclipped)
  1912.     {
  1913.       cgc = cell_gc (port, default_font(), cursor);
  1914.       XFillRectangle (port->dpy, port->window,
  1915.               cursor ? port->normal_gc : port->neutral_gc,
  1916.               colx[ci] + ov, rowy[ri] + dn,
  1917.               widths[ci], heights[ri]);
  1918.       return;
  1919.     }
  1920.   
  1921.   cgc = cell_gc (port, cd->font, cursor);
  1922.   {
  1923.     int isclipped = !xx_IRencloses (&cd->layout, &cd->goal);
  1924.     char *str;
  1925.     struct xx_sIntRectangle *strbox;
  1926.     
  1927.     if (!isclipped)
  1928.       {
  1929.     str = cd->unclipped;
  1930.     strbox = &cd->goal;
  1931.       }
  1932.     else
  1933.       {
  1934.     if (!cd->clipped)
  1935.       {
  1936.         int chr_scale = XTextWidth (cgc->font, "8", 1);
  1937.         int w_avail = xx_IRw (&cd->layout) / chr_scale;
  1938.         int cell_wid = widths[ci] / chr_scale;
  1939.         CELL *cp = find_cell (r, c);
  1940.         cd->clipped =
  1941.           ck_savestr (adjust_prc (cd->unclipped, cp, w_avail, cell_wid,
  1942.                       cd->justification));
  1943.         place_text (&cd->clip, disp, cd, cgc->font, cd->clipped);
  1944.       }
  1945.     str = cd->clipped;
  1946.     strbox = &cd->clip;
  1947.       }
  1948.     XDrawImageString (port->dpy, port->window, cgc->gc,
  1949.               strbox->x + ov, strbox->y + cgc->font->ascent + dn,
  1950.               str, strlen (str));
  1951.     {
  1952.       struct xx_sIntRectangle tofill[4];
  1953.       int fillc;
  1954.       
  1955.       fillc = xx_IRsubtract (tofill, &cd->layout, strbox);
  1956.       {
  1957.     XGCValues v;
  1958.     v.foreground = cursor ? port->fg_color_pixel : port->bg_color_pixel;
  1959.     v.background = cursor ? port->bg_color_pixel : port->fg_color_pixel;
  1960.     XChangeGC (port->dpy, cgc->gc, GCForeground | GCBackground, &v);
  1961.     cgc->cursor = !cursor;
  1962.       }
  1963.       while (fillc--)
  1964.     XFillRectangle (port->dpy, port->window, cgc->gc,
  1965.             tofill[fillc].x + ov, tofill[fillc].y + dn,
  1966.             tofill[fillc].w, tofill[fillc].h);
  1967.     }
  1968.   }
  1969. }
  1970.  
  1971.  
  1972. /* Cell values */
  1973. #ifdef __STDC__
  1974. static void
  1975. set_cursor (int on)
  1976. #else
  1977. static void
  1978. set_cursor (on)
  1979.      int on;
  1980. #endif
  1981. {
  1982.   struct x_window *xwin = x_win (thePort, cwin, 0);
  1983.   struct display *disp = &xwin->display;
  1984.   int *rowy = disp->rowy;
  1985.   int *colx = disp->colx;
  1986.   int *widths = disp->widths;
  1987.   int *heights = disp->heights;
  1988.   int ri = curow - disp->range.lr;
  1989.   int ci = cucol - disp->range.lc;
  1990.   int ov = xwin->win->win_over;
  1991.   int dn = xwin->win->win_down;
  1992.   struct cell_display *cd = cell_display_of (disp, curow, cucol);
  1993.   struct xx_sIntRectangle clip;
  1994.  
  1995.   thePort->cursor_visible = on;
  1996.  
  1997.   if (xwin->layout_needed == new_display)
  1998.     return;
  1999.  
  2000.   if (cd->used_by == cd)
  2001.     {
  2002.       clip = cd->layout;
  2003.       clip.x += ov;
  2004.       clip.y += dn;
  2005.     }
  2006.   else
  2007.     xx_IRinit (&clip,
  2008.            colx[ci] + ov, rowy[ri] + dn,
  2009.            widths[ci], heights[ri]);
  2010.   clip_to_intrectangle (&clip);
  2011.   draw_cell (xwin, cd, on);
  2012. }
  2013.  
  2014. #ifdef __STDC__
  2015. static void
  2016. xio_hide_cell_cursor (void)
  2017. #else
  2018. static void
  2019. xio_hide_cell_cursor ()
  2020. #endif
  2021. {
  2022.   if (thePort->cursor_visible)
  2023.     {
  2024.       thePort->cursor_visible = 0;
  2025.       set_cursor (0);
  2026.     }
  2027. }
  2028.  
  2029. #ifdef __STDC__
  2030. static void
  2031. xio_display_cell_cursor (void)
  2032. #else
  2033. static void
  2034. xio_display_cell_cursor ()
  2035. #endif
  2036. {
  2037.   if (!thePort->cursor_visible)
  2038.     {
  2039.       thePort->cursor_visible = 1;
  2040.       set_cursor (1);
  2041.     }
  2042. }
  2043.  
  2044.  
  2045. #ifdef __STDC__
  2046. static void
  2047. draw_labels (void)
  2048. #else
  2049. static void
  2050. draw_labels ()
  2051. #endif
  2052. {
  2053.   struct x_window *xwin;
  2054.   XRectangle rect;
  2055.   for (xwin = thePort->xwins; xwin; xwin = xwin->next)
  2056.     if (xwin->win->lh_wid && xwin->label_damage)
  2057.       {
  2058.     XGCValues gcv;
  2059.     struct window *win = xwin->win;
  2060.     int wid2 = win->lh_wid / 2;
  2061.     XFillRectangle (thePort->dpy, thePort->window,
  2062.             thePort->label_standout_gc,
  2063.             win->win_over - win->lh_wid,
  2064.             win->win_down - label_rows,
  2065.             wid2, label_rows);
  2066.     gcv.line_width = win->lh_wid;
  2067.     gcv.cap_style = CapRound;
  2068.     XChangeGC (thePort->dpy, thePort->label_gc,
  2069.            GCLineWidth | GCCapStyle, &gcv);
  2070.     XDrawLine (thePort->dpy, thePort->window, thePort->label_gc,
  2071.            win->win_over - wid2,
  2072.            win->win_down - label_rows + wid2,
  2073.            win->win_over - wid2,
  2074.            win->win_down + win->numr - wid2);
  2075.     gcv.cap_style = CapButt;
  2076.     XChangeGC (thePort->dpy, thePort->label_gc, GCCapStyle, &gcv);
  2077.     XDrawLine (thePort->dpy, thePort->window, thePort->label_gc,
  2078.            win->win_over - wid2,
  2079.            win->win_down + win->numr - wid2,
  2080.            win->win_over - wid2,
  2081.            win->win_down + win->numr);
  2082.     XFillRectangle (thePort->dpy, thePort->window, thePort->label_gc,
  2083.             win->win_over - wid2,
  2084.             win->win_down - label_rows,
  2085.             win->numc + wid2,
  2086.             label_rows);
  2087.     
  2088.     rect.x = 0;
  2089.     rect.y = 0;
  2090.     rect.width = scr_cols;
  2091.     rect.height = scr_lines;
  2092.     XSetClipRectangles (thePort->dpy, thePort->label_standout_gc,
  2093.                 0, 0, &rect, 1, YXBanded);
  2094.     {
  2095.       char buf[100];
  2096.       CELLREF cr;
  2097.       int x;
  2098.       int len;
  2099.       
  2100.       sprintf (buf, "#%d", 1 + win - wins);
  2101.       for (x = len = 0; buf[x]; ++x)
  2102.         {
  2103.           int cwid = XTextWidth (thePort->label_font, buf, 1);
  2104.           if (cwid + len > wid2)
  2105.         break;
  2106.           len += cwid;
  2107.         }
  2108.       XDrawImageString (thePort->dpy, thePort->window,
  2109.                 thePort->label_standout_gc,
  2110.                 win->win_over - wid2,
  2111.                 win->win_down - thePort->label_font->descent,
  2112.                 buf, x);
  2113.       
  2114.       rect.x = win->win_over - win->lh_wid;
  2115.       rect.y = win->win_down;
  2116.       rect.width = win->lh_wid;
  2117.       rect.height = win->numr;
  2118.       XSetClipRectangles (thePort->dpy, thePort->label_standout_gc,
  2119.                   0, 0, &rect, 1, YXBanded);
  2120.       
  2121.       x = win->win_down + thePort->label_font->ascent;
  2122.       for (cr = win->screen.lr; cr <= win->screen.hr; ++cr)
  2123.         {
  2124.           int hgt = get_scaled_height (cr);
  2125.           if (hgt)
  2126.         {
  2127.           if (a0)
  2128.             sprintf (buf, "%d", cr);
  2129.           else
  2130.             sprintf (buf, "R%d", cr);
  2131.           XDrawImageString (thePort->dpy, thePort->window,
  2132.                     thePort->label_standout_gc,
  2133.                     win->win_over - win->lh_wid, x,
  2134.                     buf, strlen (buf));
  2135.           x += hgt;
  2136.         }
  2137.           if (cr == MAX_ROW)
  2138.         break;
  2139.         }
  2140.       rect.x = 0;
  2141.       rect.y = 0;
  2142.       rect.width = scr_cols;
  2143.       rect.height = scr_lines;
  2144.       XSetClipRectangles (thePort->dpy, thePort->label_standout_gc,
  2145.                   0, 0, &rect, 1, YXBanded);
  2146.       
  2147.       x = win->win_over;
  2148.       for (cr = win->screen.lc; cr <= win->screen.hc; ++cr)
  2149.         {
  2150.           int wid = get_scaled_width (cr);
  2151.           if (wid > win->numc)
  2152.         wid = win->numc;
  2153.           if (wid)
  2154.         {
  2155.           int txtwid;
  2156.           char *ptr;
  2157.           if (a0)
  2158.             ptr = col_to_str (cr);
  2159.           else
  2160.             {
  2161.               ptr = buf;
  2162.               sprintf (ptr, "C%u", cr);
  2163.             }
  2164.           txtwid = XTextWidth (thePort->label_font, ptr, strlen (ptr));
  2165.           if (txtwid > wid - thePort->label_font->max_bounds.width)
  2166.             {
  2167.               int txtlen =
  2168.             ((wid - thePort->label_font->max_bounds.width)
  2169.              / XTextWidth (thePort->label_font, "#", 1));
  2170.               txtwid = txtlen * XTextWidth (thePort->label_font,
  2171.                             "#", 1);
  2172.               buf[txtlen] = 0;
  2173.               while (txtlen)
  2174.             buf[txtlen--] = '#';
  2175.               ptr = buf;
  2176.             }
  2177.           XDrawImageString (thePort->dpy, thePort->window,
  2178.                     thePort->label_standout_gc,
  2179.                     x + (wid - txtwid) / 2,
  2180.                     (win->win_down
  2181.                      - thePort->label_font->descent),
  2182.                     ptr, strlen (ptr));
  2183.           x += wid;
  2184.         }
  2185.           if (cr == MAX_COL)
  2186.         break;
  2187.         }
  2188.     }
  2189.     xwin->label_damage = 0;
  2190.       }
  2191. }
  2192.  
  2193.  
  2194. /* Refresh the existing image. */
  2195.  
  2196. #ifdef __STDC__
  2197. static void
  2198. xio_redisp (void)
  2199. #else
  2200. static void
  2201. xio_redisp ()
  2202. #endif
  2203. {
  2204.   static int was_text = 0;
  2205.   if (text_lines)
  2206.     {
  2207.       if (text_damaged)
  2208.     {
  2209.       struct text_line *l = text_lines;
  2210.       int row = text_rows - 1;    /* bottom row of current line */
  2211.       while (l)
  2212.         {
  2213.           XDrawImageString (thePort->dpy, thePort->window,
  2214.                 (l->standout
  2215.                  ? thePort->text_line_standout_gc
  2216.                  : thePort->text_line_gc),
  2217.                 0, row - thePort->text_line_font->descent,
  2218.                 l->line, l->nchars);
  2219.           row -= (thePort->text_line_font->ascent
  2220.               + thePort->text_line_font->descent);
  2221.           l = l->next;
  2222.         }
  2223.       text_damaged = 0;
  2224.       was_text = 1;
  2225.     }
  2226.     }
  2227.   else
  2228.     {
  2229.       struct x_window *xwin;
  2230.       if (was_text)
  2231.     {
  2232.       was_text = 0;
  2233.       XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  2234.               0, 0, scr_cols, scr_lines);
  2235.       record_damage (thePort, 0, 0, scr_cols, scr_lines);
  2236.     }
  2237.       if (thePort->redisp_needed)
  2238.     {
  2239.       thePort->redisp_needed = 0;
  2240.       draw_input ();
  2241.       draw_status ();
  2242.       draw_labels ();
  2243.       for (xwin = thePort->xwins; xwin; xwin = xwin->next)
  2244.         {
  2245.           struct display *disp = &xwin->display;
  2246.           int ov = xwin->win->win_over;
  2247.           int dn = xwin->win->win_down;
  2248.           struct cell_display * cd;
  2249.           struct cell_display * cursor_cd = 0;
  2250.           int must_draw_cursor;
  2251.  
  2252.           if (xwin->layout_needed)
  2253.         {
  2254.           layout (disp);
  2255.           xwin->layout_needed = 0;
  2256.         }
  2257.  
  2258.           /* If the cursor cell has been damaged, 
  2259.             * it will be redrawn.  However, if the 
  2260.            * cursor cell is empty, then redrawing
  2261.            * some other cell might damage the cursor.
  2262.            * This watches for that condition and
  2263.            * redraws the cursor if it occurs.
  2264.            */
  2265.           must_draw_cursor = 0;
  2266.           if (thePort->cursor_visible
  2267.           && (xwin->win == cwin)
  2268.           && (curow >= disp->range.lr)
  2269.           && (curow <= disp->range.hr)
  2270.           && (cucol >= disp->range.lc)
  2271.           && (cucol <= disp->range.hc))
  2272.         {
  2273.           cursor_cd = cell_display_of (disp, curow, cucol);
  2274.           /* If the cursor cell is not empty, we never have
  2275.            * to explicitly redraw the cursor.
  2276.            */
  2277.           if (cursor_cd->used_by == cursor_cd)
  2278.             cursor_cd = 0;
  2279.         }
  2280.  
  2281.           cd = disp->damaged;
  2282.           while (cd != (struct cell_display *) disp)
  2283.         {
  2284.           struct xx_sIntRectangle clip;
  2285.           struct cell_display *owner = cd->used_by;
  2286.           clip = owner->layout;
  2287.           clip.x += ov;
  2288.           clip.y += dn;
  2289.           clip_to_intrectangle (&clip);
  2290.           if (cursor_cd && (cd->used_by == cursor_cd->used_by))
  2291.             must_draw_cursor = 1;
  2292.           draw_cell (xwin, owner,
  2293.                  (thePort->cursor_visible
  2294.                   && (xwin->win == cwin)
  2295.                   && (owner->r == curow)
  2296.                   && (owner->c == cucol)));
  2297.           {    
  2298.             struct cell_display *cdt = cd;
  2299.             cd = cd->next_damaged;
  2300.             cdt->next_damaged = 0;
  2301.           }
  2302.         }
  2303.           disp->damaged = (struct cell_display *) disp;
  2304.           if (must_draw_cursor)
  2305.         set_cursor (1);
  2306.         }
  2307.     }
  2308.     }
  2309. }
  2310.  
  2311.  
  2312.  
  2313. #ifdef __STDC__
  2314. static XFontStruct *
  2315. reasonable_font (Xport port, char *name)
  2316. #else
  2317. static XFontStruct *
  2318. reasonable_font (port, name)
  2319.      Xport port;
  2320.      char *name;
  2321. #endif
  2322. {
  2323.   XFontStruct *f = XLoadQueryFont (port->dpy, name);
  2324.  
  2325.   if (!f)
  2326.     {
  2327.       printf("(warning) Font %s could not be loaded.\n", name);
  2328.       f = XLoadQueryFont (port->dpy, default_font_name);
  2329.       if (!f)
  2330.     {
  2331.       panic ("Default font %s could not be loaded.\n",
  2332.          default_font_name);
  2333.       exit(0);
  2334.     }
  2335.     }
  2336.   return f;
  2337. }
  2338.  
  2339. #ifdef __STDC__
  2340. extern void 
  2341. xio_open_display (void)
  2342. #else
  2343. extern void 
  2344. xio_open_display ()
  2345. #endif
  2346. {
  2347.   XGCValues gcv;
  2348.   
  2349.   thePort = (Xport) ck_malloc (sizeof (*thePort));
  2350.   thePort->cursor_visible = 1;
  2351.   thePort->redisp_needed = 1;
  2352.   thePort->xwins = 0;
  2353.   
  2354.   thePort->dpy = theDisplay;
  2355.  
  2356.   thePort->screen = DefaultScreen (thePort->dpy);
  2357.   thePort->color_map = DefaultColormap (thePort->dpy, thePort->screen);
  2358.  
  2359.   if (default_fg_color_name && 
  2360.       XParseColor (thePort->dpy, thePort->color_map, default_fg_color_name, &thePort->fg_color) &&
  2361.       XAllocColor(thePort->dpy, thePort->color_map, &thePort->fg_color))
  2362.     thePort->fg_color_pixel = thePort->fg_color.pixel;
  2363.   else
  2364.     if (default_fg_color_name && !stricmp (default_fg_color_name, "black"))
  2365.       thePort->fg_color_pixel = BlackPixel (thePort->dpy, thePort->screen);
  2366.     else
  2367.       if (default_fg_color_name && !stricmp (default_fg_color_name, "white"))
  2368.     thePort->fg_color_pixel = WhitePixel (thePort->dpy, thePort->screen);
  2369.   
  2370.   if (default_bg_color_name && 
  2371.       XParseColor (thePort->dpy, thePort->color_map, default_bg_color_name, &thePort->bg_color) &&
  2372.       XAllocColor(thePort->dpy, thePort->color_map, &thePort->bg_color))
  2373.     thePort->bg_color_pixel = thePort->bg_color.pixel;
  2374.   else
  2375.     if (default_bg_color_name && !stricmp (default_bg_color_name, "black"))
  2376.       thePort->bg_color_pixel = BlackPixel (thePort->dpy, thePort->screen);
  2377.     else
  2378.       if (default_bg_color_name && !stricmp (default_bg_color_name, "white"))
  2379.     thePort->fg_color_pixel = WhitePixel (thePort->dpy, thePort->screen);
  2380.  
  2381.   thePort->window =
  2382.     XCreateSimpleWindow (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2383.              geom_x, geom_y, geom_w, geom_h,
  2384.              1, thePort->fg_color_pixel, thePort->bg_color_pixel);
  2385.   XStoreName (thePort->dpy, thePort->window, oleo_version_string);
  2386.  
  2387.   gcv.foreground = thePort->bg_color_pixel;
  2388.   gcv.background = thePort->bg_color_pixel;
  2389.   thePort->neutral_gc =
  2390.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2391.            (GCForeground | GCBackground), &gcv);
  2392.   
  2393.   gcv.foreground = thePort->fg_color_pixel;
  2394.   gcv.background = thePort->bg_color_pixel;
  2395.   thePort->normal_gc =
  2396.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2397.            (GCForeground | GCBackground), &gcv);
  2398.   
  2399.   gcv.foreground = thePort->bg_color_pixel;
  2400.   gcv.background = thePort->fg_color_pixel;
  2401.   thePort->standout_gc =
  2402.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2403.            (GCForeground | GCBackground), &gcv);
  2404.   
  2405.   thePort->input_font = reasonable_font (thePort, input_font_name);
  2406.   gcv.font = thePort->input_font->fid;
  2407.   gcv.foreground = thePort->fg_color_pixel;
  2408.   gcv.background = thePort->bg_color_pixel;
  2409.   thePort->input_gc =
  2410.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2411.            (GCForeground | GCBackground | GCFont), &gcv);
  2412.   
  2413.   gcv.foreground = thePort->bg_color_pixel;
  2414.   gcv.background = thePort->fg_color_pixel;
  2415.   thePort->standout_input_gc =
  2416.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2417.            (GCForeground | GCBackground | GCFont), &gcv);
  2418.   
  2419.   gcv.foreground = thePort->fg_color_pixel;
  2420.   gcv.background = thePort->bg_color_pixel;
  2421.   thePort->status_font = reasonable_font (thePort, status_font_name);
  2422.   gcv.font = thePort->status_font->fid;
  2423.   thePort->status_gc =
  2424.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2425.            (GCForeground | GCBackground | GCFont), &gcv);
  2426.   
  2427.   thePort->label_font = reasonable_font (thePort, label_font_name);
  2428.   gcv.font = thePort->label_font->fid;
  2429.   gcv.cap_style = CapRound;
  2430.   thePort->label_gc =
  2431.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2432.            (GCForeground | GCBackground | GCFont | GCCapStyle), &gcv);
  2433.   
  2434.   gcv.background = thePort->fg_color_pixel;
  2435.   gcv.foreground = thePort->bg_color_pixel;
  2436.   thePort->label_standout_gc =
  2437.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2438.            (GCForeground | GCBackground | GCFont | GCCapStyle), &gcv);
  2439.   
  2440.   gcv.background = thePort->bg_color_pixel;
  2441.   gcv.foreground = thePort->fg_color_pixel;
  2442.   thePort->text_line_font = reasonable_font (thePort, text_line_font_name);
  2443.   gcv.font = thePort->text_line_font->fid;
  2444.   thePort->text_line_gc =
  2445.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2446.            (GCForeground | GCBackground | GCFont), &gcv);
  2447.   
  2448.   gcv.background = thePort->fg_color_pixel;
  2449.   gcv.foreground = thePort->bg_color_pixel;
  2450.   thePort->text_line_standout_gc =
  2451.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2452.            (GCForeground | GCBackground | GCFont), &gcv);
  2453.   
  2454.   gcv.background = thePort->fg_color_pixel;
  2455.   gcv.foreground = thePort->bg_color_pixel;
  2456.   thePort->text_line_standout_gc =
  2457.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2458.            (GCForeground | GCBackground | GCFont), &gcv);
  2459.   
  2460.   gcv.background = thePort->bg_color_pixel;
  2461.   gcv.foreground = thePort->fg_color_pixel;
  2462.   
  2463.   {
  2464.     int x;
  2465.     for (x = 0; x < GC_CACHE_SIZE; ++x)
  2466.       {
  2467.     struct cell_gc *cg =
  2468.       (struct cell_gc *) ck_malloc (sizeof (struct cell_gc));
  2469.     cg->font_name = 0;
  2470.     cg->font = 0;
  2471.     cg->clipped_to = 0;
  2472.     cg->cursor = 0;
  2473.     cg->gc = XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2474.                 (GCForeground | GCBackground), &gcv);
  2475.     if (!cell_gc_cache)
  2476.       {
  2477.         cg->next = cg;
  2478.         cg->prev = cg;
  2479.       }
  2480.     else
  2481.       {
  2482.         cg->next = cell_gc_cache;
  2483.         cg->prev = cg->next->prev;
  2484.         cg->next->prev = cg;
  2485.         cg->prev->next = cg;
  2486.       }
  2487.     cell_gc_cache = cg;
  2488.       }
  2489.   }
  2490.   
  2491.   XSelectInput (thePort->dpy, thePort->window,
  2492.         (ExposureMask | StructureNotifyMask | KeyPressMask
  2493.          | ButtonPressMask));
  2494.   
  2495.   io_init_windows (geom_h, geom_w, 1, 2,
  2496.            thePort->input_font->ascent + thePort->input_font->descent,
  2497.            (thePort->status_font->ascent
  2498.             + thePort->status_font->descent),
  2499.            thePort->label_font->ascent + thePort->label_font->descent,
  2500.            thePort->label_font->max_bounds.width);
  2501.   x11_opened = 1;
  2502.   
  2503.   {
  2504.     struct cell_gc *cgc = cell_gc (thePort, default_font(), 0);
  2505.     height_scale = cgc->font->ascent + cgc->font->descent;
  2506.     width_scale = XTextWidth (cgc->font, "M", 1);
  2507.   }
  2508.   XMapWindow (thePort->dpy, thePort->window);
  2509. }
  2510.  
  2511. #ifdef __STDC__
  2512. extern void
  2513. xio_close_display (void)
  2514. #else
  2515. extern void
  2516. xio_close_display ()
  2517. #endif
  2518. {
  2519.   XCloseDisplay (thePort->dpy);
  2520.   x11_opened = 0;
  2521. }
  2522.  
  2523. #ifdef __STDC__
  2524. static void
  2525. xio_flush (void)
  2526. #else
  2527. static void
  2528. xio_flush ()
  2529. #endif
  2530. {
  2531.   XFlush (theDisplay);
  2532. }
  2533.  
  2534.  
  2535.  
  2536.  
  2537. #define _io_open_display xio_open_display
  2538. #define _io_redisp xio_redisp
  2539. #define _io_repaint xio_repaint
  2540. #define _io_repaint_win xio_repaint_win
  2541. #define _io_close_display xio_close_display
  2542. #define _io_input_avail xio_input_avail
  2543. #define _io_scan_for_input xio_scan_for_input
  2544. #define _io_wait_for_input xio_wait_for_input
  2545. #define _io_read_kbd xio_read_kbd
  2546. #define _io_nodelay xio_nodelay
  2547. #define _io_getch xio_getch
  2548. #define _io_get_chr xio_get_chr
  2549. #define _io_get_line xio_get_line
  2550. #define _io_update_status xio_update_status
  2551. #define _io_info_msg xio_info_msg
  2552. #define _io_error_msg xio_error_msg
  2553. #define _io_text_start xio_text_start
  2554. #define _io_text_line xio_text_line
  2555. #define _io_text_finish xio_text_finish
  2556. #define _io_flush xio_flush
  2557. #define _io_clear_input_before xio_clear_input_before
  2558. #define _io_clear_input_after xio_clear_input_after
  2559. #define _io_pr_cell_win xio_pr_cell_win
  2560. #define _io_hide_cell_cursor xio_hide_cell_cursor
  2561. #define _io_display_cell_cursor xio_display_cell_cursor
  2562. #define _io_cellize_cursor xio_cellize_cursor
  2563. #define _io_inputize_cursor xio_inputize_cursor
  2564.  
  2565. #ifdef __STDC__
  2566. void x11_graphics (void)
  2567. #else
  2568. void x11_graphics ()
  2569. #endif
  2570. {
  2571.   IO_SETUP;
  2572. }
  2573.  
  2574. #ifdef __STDC__
  2575. void
  2576. set_x_default_point_size (char * str)
  2577. #else
  2578. void
  2579. set_x_default_point_size (str)
  2580.      char * str;
  2581. #endif
  2582. {
  2583.   int l = atoi (str);
  2584.   if (l > 4)
  2585.     {
  2586.       cell_font_point_size = l;
  2587.       {
  2588.     struct cell_gc *cgc = cell_gc (thePort, default_font(), 0);
  2589.     height_scale = cgc->font->ascent + cgc->font->descent;
  2590.     width_scale = cgc->font->max_bounds.width;
  2591.       }
  2592.       io_set_scr_size (scr_lines, scr_cols);
  2593.     }
  2594. }
  2595.  
  2596.  
  2597. #endif /* HAVE_X11_X_H */
  2598.  
  2599.